package org.jeecg.common.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class BeanConvertUtil {

    static {
        DateConverter dateConverter = new DateConverter();
        ConvertUtils.register(dateConverter, java.util.Date.class);
        ConvertUtils.register(new BigDecimalConverter(null), java.math.BigDecimal.class);
        ConvertUtils.register(new IntegerConverter(null), Integer.class);
    }

    /**
     * 转换Map至Bean
     *
     * @param sources     map数据源
     * @param targetClass 复制属性值至的对象对应的类
     * @param <T>         复制属性值至的对象对应的类
     * @return 复制属性后的对象
     */
    public static <T> List<T> convert(List<Map<String, Object>> sources, Class<T> targetClass) {

        return convert(sources,targetClass,false);
    }

    /**
     * 转换Map至Bean
     *
     * @param sources     map数据源
     * @param targetClass 复制属性值至的对象对应的类
     * @param <T>         复制属性值至的对象对应的类
     * @return 复制属性后的对象
     * underlineToCamel驼峰转换  xxx_abc -> xxxAbc
     */
    public static <T> List<T> convert(List<Map<String, Object>> sources, Class<T> targetClass,boolean underlineToCamel) {
        List<T> results = new ArrayList<T>();
        try {
            T result = null;
            for (Map<String, Object> source : sources) {
                Map re_map = source;
                if(underlineToCamel){
                    re_map = new HashMap();
                    for (Map.Entry<String, Object> entry : source.entrySet()) {
                        re_map.put(underlineToCamel(entry.getKey()),entry.getValue());
                    }
                }
                result = (T) new JSONObject(re_map).toJavaObject(targetClass);

                results.add(result);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return results;
    }

    /**
     * 转换List至Bean
     *
     * @param sources     map数据源
     * @param targetClass 复制属性值至的对象对应的类
     * @param <T>         复制属性值至的对象对应的类
     * @return 复制属性后的对象
     */
    public static <T> List<T> convertList(List<Object> sources, Class<T> targetClass) {
        List<T> results = new ArrayList<T>();
        try {
            if (sources != null) {
                T result = null;
                for (Object source : sources) {
                    result = targetClass.newInstance();
                    BeanUtils.copyProperties(result, source);
                    results.add(result);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return results;
    }



    /**
     * 转换Map至对象
     *
     * @param source      map数据源
     * @param targetClass 复制属性值至的对象
     * @param <T>         targetObj所属类
     * @return targetObj(复制属性后的对象)
     * @throws Exception 复制反射异常
     */
    public static <T> T convert(Map source, Class<T> targetClass) {
        T result = null;
        try {
            result = targetClass.newInstance();
            if (source != null && result != null) {
                BeanUtils.copyProperties(result, source);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 转换Map至对象
     *
     * @param source    map数据源
     * @param targetObj 复制属性值至的对象
     * @param <T>       targetObj所属类
     * @return targetObj(复制属性后的对象)
     * @throws Exception 复制反射异常
     */
    public static <T> T convert(Map<String, Object> source, T targetObj) {
        try {
            if (source != null && targetObj != null) {
                BeanUtils.copyProperties(targetObj, source);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return targetObj;
    }
    /**
     * 转换Map至对象
     *
     * @param source    map数据源
     * @param targetObj 复制属性值至的对象
     * @param <T>       targetObj所属类
     * @return targetObj(复制属性后的对象)
     * @throws Exception 复制反射异常
     */
    public static <T> void convert(Map<String, Object> source, T... targetObj) {
        try {
            if (source != null && targetObj != null) {
                for (T obj : targetObj) {
                    BeanUtils.copyProperties(obj, source);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 转换对象至map
     */
    public static <T>Map convertBeanToMap(T source) {
        Map map = new HashMap();
        try {
            if (source != null) {
                BeanUtils.copyProperties(map, source);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return map;
    }
    /**
     * 转换对象至map
     */
    public static <T>List<Map> convertBeanToMap(List<T> sources) {
        List results = new ArrayList<T>();
        try {

            if (sources != null) {
                Map map = null;
                for (Object source : sources) {
                    map = new HashMap();
                    BeanUtils.copyProperties(map, source);
                    results.add(map);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return results;

    }

    /**
     * 转换Map至对象
     * underlineToCamel驼峰转换  xxx_abc -> xxxAbc
     */
    public static <T> T convert(Map<String, Object> source, T targetObj, boolean underlineToCamel) {
        Map re_map = source;
        if(underlineToCamel){
            re_map = new HashMap();
            for (Map.Entry<String, Object> entry : source.entrySet()) {
                re_map.put(underlineToCamel(entry.getKey()),entry.getValue());
            }
        }
        try {
            targetObj = (T) new JSONObject(re_map).toJavaObject(targetObj.getClass());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return targetObj;
    }


    /**
     * 驼峰命名xxx_abc -> xxxAbc
     */
    public static String underlineToCamel(String name) {
        Assert.notNull(name, "The 'name' must not be null!");
        name = name.trim();
        if( name.contains("_")){
            int len = name.length();
            StringBuilder sb = new StringBuilder(len);
            for (int i = 0; i < len; i++) {
                char c = name.charAt(i);
                if (c == '_') {
                    if (++i < len) {
                        sb.append(Character.toUpperCase(name.charAt(i)));
                    }
                } else {
                    sb.append(c);
                }
            }
            return sb.toString();
        }else {
            return name;
        }
    }

    /** 驼峰转下划线*/
    public static String camelToUnderline(String str) {
        Pattern humpPattern = Pattern.compile("[A-Z]");
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        String s = sb.toString();
        if(s.startsWith("_")){
            s = s.substring(1);
        }
        return s;
    }

}
